package card.manager;

import card.constant.CardConst;
import card.context.BaseContext;
import card.context.PlatformContext;
import card.player.AbstractPlayer;
import card.player.Player;
import card.player.PlayerModel;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 平台管理器
 * 管理洗牌，发牌方法，结算方法，管理所有玩家
 * @author: ly
 * @date: 2020/8/20 18:04
 */
@Data
public class PlatformManager implements Manager {
    /**
     * 纸牌容器
     */
    private List<String> cardContainer = new ArrayList<>();
    /**
     * 底牌
     */
    private List<String> bottom = new ArrayList<>();
    /**
     * 玩家数组
     */
    private AbstractPlayer[] playerArr = new AbstractPlayer[]{};
    /**
     * 玩家Map key：id
     */
    private Map<String, Player> playerMap = new HashMap<>();

    /**
     * 初始化纸牌容器
     *
     * @return Manager
     */
    @Override
    public Manager cardInit() {
        //初始化54张牌
        cardContainer.addAll(CardConst.CARD_POINTS);
        cardContainer.addAll(CardConst.CARD_POINTS);
        cardContainer.addAll(CardConst.CARD_POINTS);
        cardContainer.addAll(CardConst.CARD_POINTS);
        cardContainer.addAll(CardConst.CARD_SPE);
        System.out.println("纸牌初始化成功！");
        return this;
    }

    /**
     * 洗牌
     *
     * @return Manager
     */
    @Override
    public Manager shuffle() {
        Collections.shuffle(cardContainer);
        System.out.println("洗牌完成!");
        return this;
    }

    /**
     * 发牌，给多个玩家发牌，轮询发
     *
     * @param players 玩家数组
     * @return Manager
     */
    @Override
    public Manager giveCards(AbstractPlayer... players) {
        System.out.println("发牌中......");
        if (cardContainer.size() > 0 && players.length > 0) {
            //定义轮询初始化值
            int lx = players.length;
            for (int i = 0; i < cardContainer.size() - CardConst.BOTTOM_NUM; i++) {
                AbstractPlayer player = players[lx++ % players.length];
                player.accept(cardContainer.get(i));
            }
            //将剩余的牌放入底牌
            bottom.addAll(cardContainer.subList(cardContainer.size() - CardConst.BOTTOM_NUM, cardContainer.size()));
            //存放玩家
            playerArr = players;
            playerMap.putAll(Arrays.stream(players).collect(Collectors.toMap(AbstractPlayer::getId, a -> a)));
            System.out.println("发牌完毕!");
        } else {
            System.out.println("!!!纸牌或玩家创建失败!!!");
        }
        return this;
    }

    /**
     * 结算
     *
     * @param player 当前玩家
     * @return Manager
     */
    @Override
    public Manager settle(AbstractPlayer player) {
        if (player.getCardNum() == 0) {
            System.out.println("玩家：" + player.getId() + "[" + player.getMark() + "]" + " 获胜。");
        }
        return this;
    }

    /**
     * 注册全局容器
     *
     * @param context 全局参数
     * @return Manager
     */
    @Override
    public Manager register(PlatformContext context) {
        BaseContext.setContext(context);
        return this;
    }

    /**
     * 构建实体
     *
     * @return PlatformManager
     */
    public static PlatformManager build() {
        return new PlatformManager();
    }

    /**
     * 根据id获取玩家
     *
     * @param id 玩家id
     * @return 具体玩家
     */
    @Override
    public PlayerModel getPlayer(String id) {
        return (PlayerModel) this.playerMap.get(id);
    }

    /**
     * 获取随机玩家
     *
     * @return 具体玩家
     */
    @Override
    public PlayerModel getRandomPlayer() {
        return (PlayerModel) this.playerArr[(new Random().nextInt(playerArr.length))];
    }

    /**
     * 获取下一个玩家
     *
     * @return 下一个具体玩家
     */
    @Override
    public PlayerModel getNextPlayer() {
        //当前玩家id
        String currId = BaseContext.getContext().getCurrId();
        if (StringUtils.isBlank(currId)) {
            System.out.println("!!没有设置当前玩家id,随机获取一个!!");
            return getRandomPlayer();
        }
        //下一个玩家id,默认第一个
        String next = playerArr[0].getId();
        for (int i = 0; i < this.playerArr.length - 1; i++) {
            if (this.playerArr[i].getId().equalsIgnoreCase(currId)) {
                if (i == this.playerArr.length - 1) {
                    next = playerArr[0].getId();
                } else {
                    next = playerArr[i + 1].getId();
                }
                break;
            }
        }
        return getPlayer(next);
    }

    /**
     * 获取下一个玩家，只获取一轮
     *
     * @param firstId 从哪个玩家开始算
     * @return 下一个具体玩家
     */
    @Override
    public PlayerModel getNextPlayerRound(String firstId) {
        for (; ; ) {
            PlayerModel nextPlayer = getNextPlayer();
            if (nextPlayer.getId().equals(firstId)) {
                return null;
            }
            return nextPlayer;
        }
    }
}
